package open.panxiong.shared.http.controller

import android.content.Context
import android.util.Log
import fi.iki.elonen.NanoHTTPD.IHTTPSession
import fi.iki.elonen.NanoHTTPD.Response
import fi.iki.elonen.NanoHTTPD.getMimeTypeForFile
import open.panxiong.shared.http.annotation.NanohttpdApi
import open.panxiong.shared.http.config.ConstConfig
import open.panxiong.shared.http.model.FileItem
import open.panxiong.shared.http.model.NanohttpdResponse
import open.panxiong.shared.util.getZipFileName
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.net.URLDecoder
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

class FileController {
    /**
     * 获取文件列表
     */
    @NanohttpdApi("/api/file-list")
    fun getFileList(context: Context, session: IHTTPSession): Response {
        try {
            val items = mutableListOf<FileItem>()
            val fileList = ConstConfig.getShareFileList(context)
            for (file in fileList) {
                if (!file.isFile) {
                    continue
                }
                val item = FileItem()
                item.name = file.name
                item.size = file.length()
                item.url = "${ConstConfig.API_PREFIX_DOWNLOAD}${file.name}"
                item.type = getMimeTypeForFile(file.name)
                items.add(item)
            }
            return NanohttpdResponse(data = items).toJson()
        } catch (e: Exception) {
            return NanohttpdResponse().to500(e.message.toString())
        }
    }

    // 文件上传
    @NanohttpdApi("/api/file-upload")
    fun fileDataUpload(context: Context, session: IHTTPSession): Response {
        fun handleBodySerialNumber(body: Map<String, String>): MutableMap<String, String> {
            val mapper = mutableMapOf<String, String>()
            var index = 0
            body.forEach { (t, u) ->
                if (index < 1) {
                    mapper[t] = u
                } else {
                    mapper[t.dropLast(1)] = u   // NanoHTTPD 解析时会带上序号，需要去掉
                }
                index++
            }
            return mapper
        }
        try {
            // 获取请求体中的参数和文件数据
            var dataMapper = mutableMapOf<String, String>()
            session.parseBody(dataMapper)   // 文件默认就会缓存在默认的 cache 目录
            dataMapper = handleBodySerialNumber(dataMapper)
            // 结果信息
            val results = mutableListOf<String>()
            // 保存目录
            val dir = ConstConfig.getSharedFileDirectory(context).absolutePath
            // 遍历保存文件到指定目录
            for ((name, path) in dataMapper.entries) {
                val decodeName = URLDecoder.decode(name, Charsets.UTF_8.name())
                FileInputStream(File(path)).use { fileInput ->
                    File(dir, decodeName).let { file ->
                        file.outputStream().use { os ->
                            fileInput.copyTo(os)
                            results.add("${ConstConfig.API_PREFIX_DOWNLOAD}${decodeName}")
                        }
                    }
                }
                Log.e("上传文件", "$name -> $path -> ${dir + File.separator + decodeName}")
            }
            return NanohttpdResponse(data = results).toJson()
        } catch (e: Exception) {
            return NanohttpdResponse().to500(e.message.toString())
        }
    }

    // 文件删除
    @NanohttpdApi("/api/file-delete")
    fun fileDataDelete(context: Context, session: IHTTPSession): Response {
        var names = session.parameters["names"]?.last()
        if (names.isNullOrEmpty()) {
            return NanohttpdResponse(code = -1, msg = "文件名错误").toJson()
        }
        names = URLDecoder.decode(names, Charsets.UTF_8.name())
        val dir = ConstConfig.getSharedFileDirectory(context).absolutePath
        val deleteList = mutableListOf<String>()
        val nameList = names.split(",")
        for (name in nameList) {
            File(dir + File.separator + name).let { file ->
                if (file.exists()) {
                    val result = file.delete()
                    if (result) {
                        deleteList.add(name)
                    }
                }
            }
        }
        return NanohttpdResponse(data = deleteList).toJson()
    }

    // 构建多文件打包下载链接
    @NanohttpdApi("/api/build-package-download")
    fun buildPackageDownload(context: Context, session: IHTTPSession): Response {
        var names = session.parameters["names"]?.last()
        if (names.isNullOrEmpty()) {
            return NanohttpdResponse(code = -1, msg = "文件名错误").toJson()
        }
        names = URLDecoder.decode(names, Charsets.UTF_8.name())
        val nameList = names.split(",")
        if (nameList.isEmpty()) {
            return NanohttpdResponse(code = -1, msg = "文件名错误").toJson()
        }
        val zipFileName = getZipFileName(nameList)
        val zipFileValue = File(
            ConstConfig.getTempFileDirectory(context).absolutePath + File.separator + zipFileName
        )
        if (zipFileValue.exists() && zipFileValue.isFile) {
            return NanohttpdResponse(data = ConstConfig.API_PREFIX_DOWNLOAD + zipFileName).toJson()
        }
        val zipOutput = ZipOutputStream(FileOutputStream(zipFileValue))
        val dir = ConstConfig.getSharedFileDirectory(context).absolutePath
        for (name in nameList) {
            val file = File(dir + File.separator + name)
            val entry = ZipEntry(file.name)
            zipOutput.putNextEntry(entry)
            file.inputStream().use { it.copyTo(zipOutput) }
            zipOutput.closeEntry()
        }
        zipOutput.flush()
        zipOutput.close()
        val url = ConstConfig.API_PREFIX_DOWNLOAD + ConstConfig.TEMP_FILE_DIRECTORY + "/" + zipFileName
        return NanohttpdResponse(data = url).toJson()
    }

}